// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import TestCell from "./TestCell";

const {ccclass, property} = cc._decorator;
const PAGE_NUM = 5

class CellData
{
    public ID:number
    public Data:string
}
@ccclass
export default class InfiniteSV extends cc.Component 
{

    @property(cc.Prefab)
    public CellPrefab:cc.Prefab

    private viewNode:cc.Node
    private contentNode:cc.Node

    private cellPool:cc.NodePool

    private cellWidth:number
    private cellHeight:number
    private page_cell_num:number
    // private cur_page_index:number//当前页索引
    // private total_page_num:number//总共页数
    private end_of_range:number
    private cell_window_range:[number,number]//当前滑动范围
    private begin_content_pos:cc.Vec2
    private pageHeight:number
    private scrollThreshold:number
    private cellData:Array<CellData>
    onLoad () 
    {
        //获取节点
        console.log("InfiniteSV onLoad")
        this.viewNode = this.node.getChildByName("view")
        // this.viewNode.setContentSize(this.node.getContentSize())
        // console.log("viewNode size = ",this.viewNode.getContentSize())
        this.contentNode = this.viewNode.getChildByName("content")
        if(this.CellPrefab != null)
        {
            console.log("CellPrefab size = ",this.CellPrefab.data.getContentSize())
        }
        //计算出一页可以显示几个cell
        this.cellWidth = this.CellPrefab.data.getContentSize().width
        this.cellHeight = this.CellPrefab.data.getContentSize().height 

        this.page_cell_num = this.viewNode.getContentSize().height / this.cellHeight
        this.page_cell_num *= 1.5
        this.page_cell_num = Math.ceil(this.page_cell_num)
        //计算出每一页的高度
        this.pageHeight = this.page_cell_num * this.cellHeight
        //滑动阈值
        this.scrollThreshold = this.viewNode.getContentSize().height * 0.5
        console.log("scrollThreshold = ", this.scrollThreshold)
        console.log("every page have ",this.page_cell_num," cells")

        //一次性创建节点池
        this.cellPool = new cc.NodePool("cellpool")
        for(let i = 0;i < this.page_cell_num*PAGE_NUM;i++)
        {
            let node = cc.instantiate(this.CellPrefab)
            this.cellPool.put(node)
        }
        console.log("一次性创建 ",this.cellPool.size()," 个节点")
        
        //初始化
        this.cell_window_range = [0,0]
        this.cell_window_range[0] = 0
        //直接先加载两页
        this.cell_window_range[1] = 0 + this.page_cell_num * 2 
        //初始化一百个数据
        this.cellData = new Array<CellData>()
        for(let i=0;i < 100;i++)
        {
            let one = new CellData()
            one.ID = i
            one.Data = "i="+i
            this.cellData.push(one)
        }
        this.end_of_range = 100
        this.begin_content_pos = this.contentNode.getPosition()
    }

    start () 
    {
        console.log("InfiniteSV start")
        this.loadPageCell(this.cell_window_range[0],this.cell_window_range[1])
    }

    public OnScrollEvent(scrollview: cc.ScrollView, eventType: cc.ScrollView.EventType, CustomEventData:string)
    {
        switch(eventType)
        {
            // case cc.ScrollView.EventType.SCROLL_TO_TOP:
            //     console.log("OnScrollEvent eventType = SCROLL_TO_TOP")
            //     console.log("current page = ", this.cur_page_index)
            //     this.recyclePage(eventType)
            //     this.scrollToPreviousPage()
            //     break;
            // case cc.ScrollView.EventType.SCROLL_TO_BOTTOM:
            //     console.log("OnScrollEvent eventType = SCROLL_TO_BOTTOM")
            //     console.log("current page = ", this.cur_page_index)
            //     this.recyclePage(eventType)
            //     this.scrollToNextPage()
            //     break;
            case cc.ScrollView.EventType.SCROLLING:
                // console.log("OnScrollEvent eventType = SCROLLING")
                // console.log("content pos = ",this.contentNode.getPosition())
                let cur_pos = this.contentNode.getPosition()
                let begin_pos = this.begin_content_pos
                let move_distance = cc.Vec2.distance(begin_pos,cur_pos)
                // console.log("move_distance = ", move_distance)
                let dirction = begin_pos.sub(cur_pos)
                if(move_distance >= this.scrollThreshold)
                {//达到滑动阈值,继续加载
                    console.log("达到滑动阈值,继续加载")
                    if(dirction.y > 0)
                    {
                        console.log("向下滑动")
                        this.scrollToPreviousPage()
                        this.recyclePage(false)
                    }
                    else
                    {
                        console.log("向上滑动")
                        //加载下面的cell
                        this.scrollToNextPage()
                        this.recyclePage(true)
                    }
                    this.begin_content_pos = cur_pos
                }
                break
            // case cc.ScrollView.EventType.SCROLL_BEGAN:
            //     console.log("OnScrollEvent eventType = SCROLL_BEGAN")
            //     this.begin_content_pos = this.contentNode.getPosition()
            //     break
            // case cc.ScrollView.EventType.SCROLL_ENDED:
            //     console.log("OnScrollEvent eventType = SCROLL_ENDED")
            //     let move_distance = cc.Vec2.distance(this.begin_content_pos,this.contentNode.getPosition())
            //     console.log("move_distance = ",move_distance)
            //     break
        }
    }

    
    // private calculatePage():[number,number]
    // {
    //     let startIdx = this.cur_page_index * this.page_cell_num
    //     let endIdx = 0
    //     if(startIdx + this.page_cell_num > this.cellData.length)
    //     {
    //         endIdx = this.cellData.length - 1
    //     }
    //     else
    //     {
    //         endIdx = startIdx + this.page_cell_num
    //     }
    //     return [startIdx,endIdx]
    // }

    private recyclePage(is_scroll_up:boolean)
    {
        let child_num = this.contentNode.children.length
        if(child_num <= this.page_cell_num * 3)
        {
            return
        }
        let recycleNodes = new Array<cc.Node>()
        let count = this.page_cell_num
        if (count > child_num) {
            count = child_num
        }
        let contentNodes:cc.Node[]
        if(is_scroll_up)
        {
            //回收头部
            contentNodes = this.contentNode.children
            this.cell_window_range[0] = this.cell_window_range[0] + count
        }
        else
        {
            //回收底部
            contentNodes = this.contentNode.children.reverse()
            this.cell_window_range[1] = this.cell_window_range[1] - count
        }
        for (let i = 0; i < count; i++) {
            recycleNodes.push(contentNodes[i])
        }
        console.log("回收前 content child 数量",contentNodes.length)
        //回收到对象池
        for(let  i = 0;i < recycleNodes.length;i++)
        {
            let node = recycleNodes[i]
            node.removeFromParent(false)
            this.cellPool.put(node)
        }
        console.log("回收后 content child 数量", contentNodes.length)
        console.log("回收了", recycleNodes.length, "个节点 当前对象池中有 ", this.cellPool.size())
    }

    private scrollToPreviousPage()
    {
        let old_window_begin = this.cell_window_range[0]
        if(old_window_begin <= 0)
        {
            console.log("已经达到头部")
            return
        }
        let new_window_begin = old_window_begin - this.page_cell_num
        this.loadPageCell(old_window_begin,new_window_begin)
        this.cell_window_range[0] = new_window_begin
    }

    private scrollToNextPage()
    {
        let old_window_end = this.cell_window_range[1]
        if(old_window_end >= this.end_of_range)
        {
            console.log("已经达到底部")
            return
        }
        let new_section_end = old_window_end + this.page_cell_num
        this.loadPageCell(old_window_end, new_section_end)
        this.cell_window_range[1] = new_section_end
    }

    private loadCellAtTail(startIdx:number,endIdx:number):number
    {
        let count = 0
        for (let i = startIdx; i < endIdx; i++) {
            // console.log("加载数据 id = ",this.cellData[i].ID," data = ",this.cellData[i].Data)
            if (this.cellPool.size() > 0) {
                let node = this.cellPool.get()
                let cellObj = node.getComponent(TestCell)
                cellObj.initView(i)
                let pos = new cc.Vec2()
                pos.y = i * this.cellHeight
                pos.y = 0 - pos.y
                node.setPosition(pos)
                this.contentNode.addChild(node)
                count = count + 1
            }
            else {
                console.log("loadPageCell 对象池数据不足")
                break
            }
        }
        return count
    }
    private loadCellAtHead(startIdx: number, endIdx: number)
    {
        let count = 0
        for (let i = startIdx; i > endIdx; i--) {
            // console.log("加载数据 id = ",this.cellData[i].ID," data = ",this.cellData[i].Data)
            if (this.cellPool.size() > 0) {
                let node = this.cellPool.get()
                let cellObj = node.getComponent(TestCell)
                cellObj.initView(i)
                let pos = new cc.Vec2()
                pos.y = i * this.cellHeight
                
                node.setPosition(pos)
                this.contentNode.insertChild(node, 0)
                count = count + 1
            }
            else {
                console.log("loadPageCell 对象池数据不足")
                break
            }
        }
        return count
    }
    private loadPageCell(startIdx:number,endIdx:number)
    {
        if(endIdx > startIdx)
        {
            this.loadCellAtTail(startIdx,endIdx)
        }
        else
        {
            let count = this.loadCellAtHead(startIdx,endIdx)
            this.extendContentSize(count)
        }
        
    }

    private extendContentSize(count:number)
    {
        let contentSize = this.contentNode.getContentSize()
        contentSize.height = contentSize.height + count * this.cellHeight
        this.contentNode.setContentSize(contentSize)
    }

    // update (dt) {}
}
